package seedpod.kb2db.protegeplugin;
/**
 * Copyright 2009 University of  Washington
 * This code is released under the GPL version 3 - with a copy of the license included
 * @author Maya Hao Li
 *
 */
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;

import edu.stanford.smi.protege.storage.clips.ParseErrorPanel;
import edu.stanford.smi.protege.ui.ProjectManager;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

import seedpod.kb2db.Protege2Rdb;
import seedpod.kb2db.RdbSchemaWriter;
import seedpod.model.rdb.Rdb;
import edu.stanford.smi.protege.Application;
import edu.stanford.smi.protege.model.KnowledgeBase;
import edu.stanford.smi.protege.model.Project;
import edu.stanford.smi.protege.plugin.ExportPlugin;
import edu.stanford.smi.protege.util.ApplicationProperties;
import edu.stanford.smi.protege.util.ComponentFactory;
import edu.stanford.smi.protege.util.ExtensionFilter;
import edu.stanford.smi.protege.util.FileUtilities;

public class Protege2SQLExportPlugin implements ExportPlugin
{
	public static final String EXTENSION = ".sql";
	public static final String FILE_DESCRIPTION = "SQL file";
	private static final String PLUGIN_NAME = "Seedpod SQL Export Plugin";
	private File _exportFile;
	private Collection<String> _transformErrors;

	public String getName() {
		return PLUGIN_NAME;
	}

	// prompt for user to save to a file, which does the call to export
	// transformation
	public void handleExportRequest( Project project ) {
		boolean savedProject = ProjectManager.getProjectManager().saveProjectAsRequest();
		if (!savedProject)
			return;
		_exportFile = promptForFile( project.getName() + EXTENSION );

		boolean fileSaved = false;
		if ( _exportFile != null ) {
			fileSaved = saveToFile( project, _exportFile );
			if ( fileSaved ) {
				displayTransformErrorMessages( _exportFile, _transformErrors );
			}
		}
	}

	public File getExportFile() {
		return _exportFile;
	}

	/*
	 * a split pane window (top/down divided) top: exported file; bottom, error
	 * messages
	 */
	private static void displayTransformErrorMessages( File file, Collection<?> errorMessages ) {
		// create split pane in a frame
		JSplitPane splitPane = ComponentFactory.createTopBottomSplitPane();

		// top: export file
		JEditorPane editor = ComponentFactory.createEditorPane();
		JScrollPane fileScrollPane = ComponentFactory.createScrollPane( editor );
		fileScrollPane.setPreferredSize( new Dimension( 600, 400 ) );

		try {
			editor.setPage( file.toURL() );
			editor.setEditable( true );
			editor.setContentType( "text/plain" );
			editor.setFocusable( true );
		}
		catch (IOException ioe) {
			editor.setText( "Exception occurred while reading from file: " + file.getName() );
		}

		// bottom:
		JScrollPane errorScrollPane = ComponentFactory.createScrollPane();
		JComponent errorPanel = new ParseErrorPanel( errorMessages );
		errorPanel.setPreferredSize( new Dimension( 600, 100 ) );
		errorScrollPane.add( errorPanel );
		errorScrollPane.setName( "Errors and Warnings" );

		splitPane.setTopComponent( fileScrollPane );
		splitPane.setBottomComponent( errorPanel );
		splitPane.setDividerLocation( 400 );
		splitPane.setResizeWeight( 0.8 );

		
		JFrame frame = ComponentFactory.showInFrame( splitPane, file.getName() );
		
		// add key listener to the editor pane in case user wants to make
		// changes
		editor.addKeyListener( new EditorContentKeyListener( frame, editor, file ) );
	}


	// private static void displayFileEditor( File file ) {
	// JEditorPane editor = ComponentFactory.createEditorPane();
	//	
	// JScrollPane scrollPane = ComponentFactory.createScrollPane( editor );
	// scrollPane.setPreferredSize( new Dimension( 700, 400 ) );
	//	
	// JFrame frame = ComponentFactory.showInFrame( scrollPane, file.getPath()
	// );
	//	
	// try {
	// editor.setEditable( true );
	// editor.setPage( file.toURL() );
	// editor.setContentType( "text/plain" );
	// editor.setFocusable( true );
	//	
	// editor.addKeyListener( new EditorContentKeyListener( frame, editor, file
	// ) );
	//	
	// }
	// catch (IOException ioe) {
	// JRootPane rootPane =
	// ProjectManager.getProjectManager().getCurrentProjectView().getRootPane();
	// JComponent c = ComponentFactory.createLabel( "Failed to read file: " +
	// file.getPath() );
	// ModalDialog.showDialog( rootPane, c, "IOException",
	// ModalDialog.MODE_OK_CANCEL );
	// }
	// }

	public void dispose() {
	// do nothing
	}

	public static void main( String[] args ) {
		Application.main( args );
	}

	public static JFileChooser createFileChooser( String title, String fileDescription, String fileExtension ) {
		File lastDirectory = ApplicationProperties.getLastFileDirectory();
		JFileChooser chooser = new JFileChooser( lastDirectory );
		chooser.setDialogTitle( title );

		if ( fileExtension == null ) {
			chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
		} else {
			String text = fileDescription;
			chooser.setFileFilter( new ExtensionFilter( fileExtension, text ) );
		}
		return chooser;
	}

	public static File promptForFile( String fileName ) {
		File proposedFile = new File( fileName );
		FileUtilities.ensureExtension( proposedFile.getPath(), EXTENSION );

		JFileChooser chooser = createFileChooser( "Save To SQL File", FILE_DESCRIPTION, EXTENSION );
		chooser.setSelectedFile( proposedFile );

		File file = null;
		if ( chooser.showSaveDialog( null ) == JFileChooser.APPROVE_OPTION ) {
			file = chooser.getSelectedFile();
		}
		return file;
	}

	private boolean saveToFile( Project project, File file ) {
		boolean saved = false;
		PrintWriter writer = FileUtilities.createPrintWriter( file, false );
		if ( exportToSQL( project, writer ) == false )
			file.delete();
		else
			saved = true;
		writer.close();
		return saved;
	}

	// Write out each class, one per line.
	private boolean exportToSQL( Project project, PrintWriter writer ) {
		boolean success = false;
		KnowledgeBase kb = project.getKnowledgeBase();
		Rdb db = new Rdb( project.getName() );

		Protege2Rdb transformer = new Protege2Rdb( kb, db );
		_transformErrors = new ArrayList<String>();
		try {
			transformer.transform();
			/** TODO prompt user for where to put the copy of the current project * */

			_transformErrors = transformer.getTransformErrors();
			_transformErrors.addAll( transformer.getTransformWarnings() );

			RdbSchemaWriter sqlGenerator = new RdbSchemaWriter( db );
			sqlGenerator.serialize( writer );
			success = true;
		}
		catch (IOException e) {
			writer.write( "Writing SQL to file failed: " + e.getLocalizedMessage() );
			ArrayList<String> err = new ArrayList<String>();
			err.add( e.getMessage() );
			displayErrors( "IOException", err );
		}
		return success;
	}

	private void displayErrors( String title, Collection<?> errors ) {
		ProjectManager manager = ProjectManager.getProjectManager();
		manager.displayErrors( title, errors );

	}
	

}
